import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.LinkedList;

public class MainFrame extends JFrame {
    public static final int WIDTH = 250;//窗口宽度，固定
    public static final int HEIGHT = 250;//窗口高度，固定
    public static final int GRID_NUMBER = (int) (WIDTH * 0.08);//一行中的格数，固定
    public static final int GRID_WIDTH = WIDTH / GRID_NUMBER;//每格长度
    public static final int STEP = GRID_WIDTH;//步进
    public static final int[] SPAWN_POINT = {WIDTH / 2, WIDTH / 2};//起始点
    public static final int INITIAL_LENGTH = 6;//初始长度
    public static final int INITIAL_DIRECT = 39;//初始方向

    public static LinkedList<Integer> xPoint = new LinkedList<>();//蛇身节点x坐标集合
    public static LinkedList<Integer> yPoint = new LinkedList<>();//蛇身节点y坐标集合
    public static ArrayList<String> xyPoint = new ArrayList<>();//将xPoint和yPoint节点的坐标以“x,y”的形式存储
    private static TimeThread timeThread;//游戏局时线程
    public static int length = 0;//当前长度
    static int direct = 0;//当前方向
    static int flag = 0;//是否正在游戏0：未开始，1：正在游戏，2：暂停中，3：已结束
    static Integer[] headPoint = new Integer[]{0, 0};//蛇头节点坐标
    private static GamePanel gamePanel;//所有的panel
    private static MoveThread moveThread;//自动移动线程

    int beginTimeMillis = 0;
    boolean insReborn = false;
    int mode = 0;
    double speed = 0.0;//行进速度
    Object game = new Object();//线程对象

    // 窗口大小不可变
    @Override
    public boolean isResizable() {
        return false;
    }

    public MainFrame() {
        // 设置 窗口标题 和 窗口大小
        setTitle("贪吃蛇2.0");
        setSize(WIDTH + 13, HEIGHT + 67 + 28 + MainFrame.WIDTH / 100);

        // 设置窗口关闭按钮的默认操作(点击关闭时退出进程)
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        // 把窗口位置设置到屏幕的中心
        setLocationRelativeTo(null);

        // 设置窗口的游戏面板
        gamePanel = new GamePanel();
        //信息（时间）面板

        //总面板
        JPanel rootPanel = new JPanel(new BorderLayout());
        rootPanel.add(gamePanel, BorderLayout.CENTER);
        rootPanel.add(new TimePanel(), BorderLayout.NORTH);

        setContentPane(rootPanel);

        //添加菜单栏
        setJMenuBar(new Menu());

        //添加键盘监听器
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //System.out.println(e.getKeyChar() + "  ----  " + e.getKeyCode());
                int keyCode = e.getKeyCode();

                //按下任意键开始
                if (flag == 0) {
                    flag = 1;
                    gameStart();
                } else if (flag == 1) {
                    switch (keyCode) {
                        //按下方向键
                        case 37:
                        case 38:
                        case 39:
                        case 40:
                            direct = keyCode;
                            //更新path
                            currentPath(keyCode);
                            break;
                        //暂停键
                        case 32:
                            flag = 2;
                            timeThread.stop();
                            moveThread.gamePause();
                            //PausePanel pausePanel = new PausePanel();
                            gamePanel.add(new PausePanel(), Integer.valueOf(300));//暂停界面
                            //System.out.println(gamePanel.getIndexOf(pausePanel));
                            //System.out.println(direct);
                            //System.out.println(TimePanel.timeText.getText());
                            break;
                        default:
                    }
                } else if (flag == 2 && keyCode == 32) {//继续游戏
                    flag = 1;
                    /*try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }*/
                    moveThread.gameContinue();
                    gamePanel.remove(0);//移除暂停界面

                    timeThread.start();
                } /*else if (keyCode == 27) {//重开
                    new MainFrame().setVisible(true);
                    dispose();
                }*/
            }

        });
    }

    private void gameStart() {
        gamePanel.remove(0);//移除欢迎界面

        //初始化重生点与长度
        for (int i = 0; i < INITIAL_LENGTH; i++) {
            superOffer(SPAWN_POINT[0] + STEP * i, SPAWN_POINT[1], 2);
        }

        //自动前进
        moveThread = new MoveThread(game);
        Thread myThread = new Thread(moveThread);
        myThread.setDaemon(true);
        myThread.start();

        //计时器
        timeThread = new TimeThread();
        timeThread.start();

        //根据初始方向自动出发
        direct = INITIAL_DIRECT;
        currentPath(direct);

        //记录初始时间
        String timeMillis = System.currentTimeMillis() + "";
        beginTimeMillis = Integer.parseInt((timeMillis).substring(timeMillis.length() - 6));
        //System.out.println(currentTimeMillis);
    }


    /**
     * 根据键盘输入方向，向路径里添加新坐标（新蛇头）
     * 移除尾坐标（如果前方不是food）
     *
     * @param keyCode 键盘输入方向
     */
    public static void currentPath(int keyCode) {
        switch (keyCode) {
            case 37://左
                if (isFood(xPoint.peekLast() - STEP, yPoint.peekLast())) {
                    superOffer(xPoint.peekLast() - STEP, yPoint.peekLast(), 1);
                } else {
                    superOffer(xPoint.peekLast() - STEP, yPoint.peekLast(), 0);
                }
                break;
            case 38://上
                if (isFood(xPoint.peekLast(), yPoint.peekLast() - STEP)) {
                    superOffer(xPoint.peekLast(), yPoint.peekLast() - STEP, 1);
                } else {
                    superOffer(xPoint.peekLast(), yPoint.peekLast() - STEP, 0);
                }
                break;
            case 39://右
                if (isFood(xPoint.peekLast() + STEP, yPoint.peekLast())) {
                    superOffer(xPoint.peekLast() + STEP, yPoint.peekLast(), 1);
                } else {
                    superOffer(xPoint.peekLast() + STEP, yPoint.peekLast(), 0);
                }
                break;
            case 40://下
                if (isFood(xPoint.peekLast(), yPoint.peekLast() + STEP)) {
                    superOffer(xPoint.peekLast(), yPoint.peekLast() + STEP, 1);
                } else {
                    superOffer(xPoint.peekLast(), yPoint.peekLast() + STEP, 0);
                }
                break;
            default:
        }
        //判断是否出界
        if (isOut()) {
            gamePanel.add(new FailPanel(), Integer.valueOf(300));//1
            moveThread.gamePause();
            timeThread.stop();
            flag = 3;
        } else {
            //更新panel
            gamePanel.getSnakePanel().updateUI();
        }
        //System.out.println(isOut());
    }

    /**
     * 在x,y处增加节点
     *
     * @param x    x坐标
     * @param y    y坐标
     * @param mode 0:先删再加; 1:直接加（吃到食物）;2:直接加（初始化）
     */
    private static void superOffer(Integer x, Integer y, int mode) {
        if (mode == 0) {
            // 弹出尾部节点
            superPoll();
            //if (!xyPoint.isEmpty()) {
            xyPoint.remove(0);
            //}
            //length--;
        } else if (mode == 2) {
            length++;
            //TimePanel.addScore(1);
        } else {
            length++;
            TimePanel.addScore(10 + extraScore());
        }
        //System.out.println("length" + length);
        //更新分数

        //判断是否撞上自己
        if (xyPoint.contains(x + "," + y)) {
            //FailPanel failPanel = new FailPanel();
            gamePanel.add(new FailPanel(), Integer.valueOf(300));//1
            //System.out.println(gamePanel.getIndexOf(failPanel));
            moveThread.gamePause();
            timeThread.stop();
            flag = 3;
        } else {//没撞上
            headPoint[0] = x;
            headPoint[1] = y;
            xPoint.offer(x);
            yPoint.offer(y);
            xyPoint.add(x + "," + y);
            //System.out.println("head: "+x+" "+y);
        }
    }



    /**
     * 弹出尾部节点
     */
    private static void superPoll() {
        //System.out.println("last rear at: " + xPoint.poll() + ", " + yPoint.poll());
        xPoint.poll();
        yPoint.poll();
    }

    static int a = 0;

    /**
     * 根据获得食物速度，给予额外分
     * @return 额外分
     */
    private static int extraScore() {
        int interval = 0;

        String timeMillis = System.currentTimeMillis() + "";
        int currentTimeMillis = Integer.parseInt((timeMillis).substring(timeMillis.length() - 6));
        //System.out.println(currentTimeMillis);
        if (a != 0) {
            interval = currentTimeMillis - a;
        }
        a = currentTimeMillis;
        if (interval != 0){
            System.out.println(interval + "  " + (100000 / (interval + 3000) - 3));
            return 100000 / (interval + 3000) - 3;
        }else {
            return 0;
        }

    }

    /**
     * 是否碰撞边框
     *
     * @return 碰撞返回true
     */
    public static boolean isOut() {
        return !(headPoint[0] >= 0 && headPoint[0] <= WIDTH &&
                headPoint[1] >= 0 && headPoint[1] <= WIDTH);
    }

    /**
     * 前方是否是食物
     *
     * @param x x坐标
     * @param y y坐标
     * @return 食物返回true
     */
    public static boolean isFood(int x, int y) {
        return x == FoodPanel.foodPoint[0] && y == FoodPanel.foodPoint[1];
    }
}